import * as vscode from 'vscode';
import { Project, SourceFile} from "ts-morph";
import { registerCommand } from './utils';
import * as _windowDemo from "./demo/vscode.window";

// 注册已有的demo
let demoFuns:{
    module:string,
    name:string,
    fun:()=>any
}[] = [];
Object.keys(_windowDemo).forEach(name => {
    demoFuns.push({
        module:"windowDemo",
        name:name,
        // @ts-ignore
        fun:_windowDemo[name]
    })
});

type elementType = "module" | "function" | "class" | "method" | "property"

enum elementTypeName {
    "module" = "模块",
    "class" = "类",
    "function" = "函数",
    "method" = "方法",
    "property" = "属性"
}

enum elementTypeIcon {
    "module" = "symbol-module",
    "class" = "symbol-class",
    "function" = "symbol-function",
    "method" = "symbol-method",
    "property" = "symbol-field"
}

interface element  {
    type:elementType
    name:string | undefined
}

interface moduleClassFun extends element  {
    module:string | undefined
}

interface classPropertyMethod extends moduleClassFun {
    class:string | undefined
}

const vsModule = "'vscode'";
export const apiCommand = 
{
    command: "diyextapi.vsApi",
    title: "DiyApi[vsApi]"
}
export const dispatchCommand = 
{
    command: "diyextapi.dispatchApi",
    title: "DiyApi[dispatchApi]"
}
// 1 初始化Project
const projectInstance = new Project();
// 3 加载源代码 相对package.json
const tsSource = projectInstance.addSourceFileAtPath(__dirname+"./../lib/vscode.d.ts");

export function registerApiTree(context: vscode.ExtensionContext)
{
    registerCommand(context,apiCommand.command,_api);
    // @ts-ignore
    registerCommand(context,dispatchCommand.command,_dispatch);
}

function _api(){
    l("apiTree");
    vscode.window.createTreeView("vsApi",{
        treeDataProvider:{
            getTreeItem:function(key:element){
                return getApiItem(key);
            },
            getChildren:function(key:element | undefined){
                return getApiChildren(key);
            },
            // resolveTreeItem:function(item,elem,token){
            //     console.log("res",item,elem,token);
            //     return undefined;
            // }
        }
    })
}
function checkDemo(item:element){
    if(item.type == "function"){
        let funItem = item as moduleClassFun;
        return demoFuns.find(
            d => d.module == funItem.module+"Demo" 
                && d.name == funItem.name+"Demo")
    
    }
    return undefined;
}
function _dispatch(item:element)
{   
    let demoFun = checkDemo(item);
    try{
        if(demoFun){
            demoFun.fun();
        }else{
            l(item.name+"尚未实现Demo");
        }
    }catch(e){
        l(e.toString());
    }
    // try{
    //     // eval(item.name+"Demo"+"();");
    // }catch(e){
    //     l(e.toString());
    // }
}
function getApiItem(item:element): vscode.TreeItem{
    return {
        label: item.name,
        tooltip: `${item.name}[${elementTypeName[item.type]}] ${checkDemo(item) != undefined
            ? "已实现": "未实现"}`,
        command:{
            ...dispatchCommand, //嵌入命令
            arguments:[item]
        },
        collapsibleState:item.type == "module" || item.type == "class"
            ? vscode.TreeItemCollapsibleState.Expanded
            : vscode.TreeItemCollapsibleState.None
    }; 
}

function getApiChildren(item?:element | undefined){
    if(!item){
        return moduleNames(tsSource,vsModule);
    }
    console.log("children",item);
    // 获取module的class和fun
    if(item.type == "module"){
        return moduleClassAndFun(tsSource,item);
    }
    if(item.type == "class"){
        return classMethodAndProperty(tsSource,item);
    }
    if(item.type == "function" 
    || item.type == "property" 
    || item.type == "method"){
        return funOrClassField(tsSource,item);
    }
    return [];
}

function moduleNames(src:SourceFile,globalModule?:string | null){
    let moduleTop = globalModule ? 
            src.getModule(globalModule)
            : src;

    let a =  moduleTop
        ?.getModules()
        .map(m=>m.getName())
        .map(name => mapToItem(name,"module"));
    
    console.log("m",a);
    return a;
}

function moduleClassAndFun(src:SourceFile,item:element):element[]{
    if(!item.name){
        return [];
    }

    const curModule = src.getModule(vsModule) 
        ?.getModule(item.name);

    const classes  = curModule
        ?.getClasses().map(c => {
        return {
            type:"class" as elementType,
            module:item.name,
            name:c.getName()
        }
    })
    const funs = curModule
        ?.getFunctions().map(f => {
            return {
                type:"function" as elementType,
                module:item.name,
                name:f.getName()
            }
        });
    
    let result = classes ? [...classes] : [];
    result = funs ? result.concat(funs) : [];

    return result;
}
function classMethodAndProperty(src:SourceFile,item:element):element[]{

    return [];
}
function funOrClassField(src:SourceFile,item:element):element[]{

    return [];
}

function mapToItem(name:string,type:elementType):element{
    return {
        name,
        type
    }
}

function l(msg:string){
    vscode.window.showInformationMessage(msg);
}

function _exeFun(funcName:string){
    l(funcName);  
    console.log(typeof(funcName));
    console.log(eval);  
    console.log(typeof(eval(funcName)));   
    if(typeof(eval(funcName)) == "function"){ 
        l("a")       
        eval(funcName+"();");
    }
    else
    {
        l("b")  
        l(funcName+"未实现")
    }
}


